package com.zzyl.nursing.websocket;

import cn.hutool.json.JSONUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;

import javax.websocket.*;
import javax.websocket.server.PathParam;
import javax.websocket.server.ServerEndpoint;
import java.io.IOException;
import java.util.concurrent.ConcurrentHashMap;

/**
 * WebSocket服务端 - 实时报警推送
 * 
 * @author zzyl
 * @date 2025-07-25
 */
@ServerEndpoint("/ws/{userId}")
@Component
@Slf4j
public class AlertWebSocketServer {

    /**
     * 存储所有在线用户的Session
     * key: userId, value: Session
     */
    private static final ConcurrentHashMap<String, Session> USER_SESSIONS = new ConcurrentHashMap<>();

    /**
     * 在线用户计数
     */
    private static int onlineCount = 0;

    /**
     * 连接建立成功调用的方法
     */
    @OnOpen
    public void onOpen(Session session, @PathParam("userId") String userId) {
        USER_SESSIONS.put(userId, session);
        addOnlineCount();
        log.info("用户 {} 建立WebSocket连接，当前在线人数：{}", userId, getOnlineCount());
        
        // 发送JSON格式的连接成功消息
        AlertMessage welcomeMessage = AlertMessage.builder()
                .notifyType(0)  // 系统消息
                .isAllConsumer(false)
                .physicalLocationType(-1)  // 系统消息不涉及物理位置
                .deviceDescription("系统连接")
                .accessLocation("WebSocket服务")
                .productName("系统")
                .functionName("连接状态")
                .dataValue("连接成功")
                .iotId("SYSTEM")
                .deviceName("WebSocket服务器")
                .productKey("SYSTEM")
                .alertLevel(0)
                .userId(Long.parseLong(userId))
                .createTime(java.time.LocalDateTime.now())
                .build();
        
        sendMessage(session, JSONUtil.toJsonStr(welcomeMessage));
    }

    /**
     * 连接关闭调用的方法
     */
    @OnClose
    public void onClose(@PathParam("userId") String userId) {
        USER_SESSIONS.remove(userId);
        subOnlineCount();
        log.info("用户 {} 断开WebSocket连接，当前在线人数：{}", userId, getOnlineCount());
    }

    /**
     * 收到客户端消息后调用的方法
     */
    @OnMessage
    public void onMessage(String message, Session session, @PathParam("userId") String userId) {
        log.info("收到用户 {} 的消息：{}", userId, message);
        
        // 可以在这里处理客户端发送的消息，比如心跳检测
        if ("ping".equals(message)) {
            // 发送JSON格式的心跳响应
            AlertMessage pongMessage = AlertMessage.builder()
                    .notifyType(0)  // 系统消息
                    .isAllConsumer(false)
                    .physicalLocationType(-1)  // 系统消息不涉及物理位置
                    .deviceDescription("心跳检测")
                    .accessLocation("WebSocket服务")
                    .productName("系统")
                    .functionName("心跳响应")
                    .dataValue("pong")
                    .iotId("SYSTEM")
                    .deviceName("WebSocket服务器")
                    .productKey("SYSTEM")
                    .alertLevel(0)
                    .userId(Long.parseLong(userId))
                    .createTime(java.time.LocalDateTime.now())
                    .build();
            
            sendMessage(session, JSONUtil.toJsonStr(pongMessage));
        }
    }

    /**
     * 发生错误时调用
     */
    @OnError
    public void onError(Session session, Throwable error, @PathParam("userId") String userId) {
        log.error("用户 {} 的WebSocket连接发生错误", userId, error);
    }

    /**
     * 发送消息给指定用户
     * 
     * @param userId 用户ID
     * @param alertMessage 报警消息对象
     */
    public static void sendAlertToUser(String userId, AlertMessage alertMessage) {
        Session session = USER_SESSIONS.get(userId);
        if (session != null && session.isOpen()) {
            try {
                String message = JSONUtil.toJsonStr(alertMessage);
                session.getBasicRemote().sendText(message);
                log.info("向用户 {} 发送报警消息：{}", userId, message);
            } catch (IOException e) {
                log.error("向用户 {} 发送消息失败", userId, e);
                // 移除异常连接
                USER_SESSIONS.remove(userId);
            }
        } else {
            log.warn("用户 {} 不在线或连接已断开", userId);
        }
    }

    /**
     * 广播消息给所有在线用户
     * 
     * @param alertMessage 报警消息对象
     */
    public static void broadcastAlert(AlertMessage alertMessage) {
        alertMessage.setIsAllConsumer(true);
        String message = JSONUtil.toJsonStr(alertMessage);
        
        USER_SESSIONS.forEach((userId, session) -> {
            if (session.isOpen()) {
                try {
                    session.getBasicRemote().sendText(message);
                    log.info("向用户 {} 广播报警消息", userId);
                } catch (IOException e) {
                    log.error("向用户 {} 广播消息失败", userId, e);
                    // 移除异常连接
                    USER_SESSIONS.remove(userId);
                }
            }
        });
        
        log.info("广播报警消息给 {} 个在线用户", USER_SESSIONS.size());
    }

    /**
     * 发送普通文本消息
     */
    private void sendMessage(Session session, String message) {
        try {
            session.getBasicRemote().sendText(message);
        } catch (IOException e) {
            log.error("发送消息失败", e);
        }
    }

    /**
     * 获取所有在线用户ID
     */
    public static java.util.Set<String> getOnlineUsers() {
        return USER_SESSIONS.keySet();
    }

    /**
     * 检查用户是否在线
     */
    public static boolean isUserOnline(String userId) {
        Session session = USER_SESSIONS.get(userId);
        return session != null && session.isOpen();
    }

    private static synchronized int getOnlineCount() {
        return onlineCount;
    }

    private static synchronized void addOnlineCount() {
        AlertWebSocketServer.onlineCount++;
    }

    private static synchronized void subOnlineCount() {
        AlertWebSocketServer.onlineCount--;
    }
} 